import * as vscode from 'vscode';
import globalDictionary from './globalStore/dictionary';
import { configInfo } from './config';

export const DIAGNOSTIC_IDENT = ' Project Dictionary';
let diagnosticCollection: vscode.DiagnosticCollection;

export const diagnosticActiveTextEditor = _diagnosticActiveTextEditor;

async function _diagnosticActiveTextEditor() {
  if (!vscode.window.activeTextEditor) {return;}

  const { uri, fileName, languageId } = vscode.window.activeTextEditor.document;
  if (fileName === configInfo.filePath) {return;}
  if (!languageId) {return;}

  if (!diagnosticCollection) {diagnosticCollection = vscode.languages.createDiagnosticCollection(languageId);}
  
  const diagnostics = detectSynonyms();
  diagnosticCollection.set(uri, diagnostics);
}

function detectSynonyms() {
  const { document } = vscode.window.activeTextEditor!;

  const text = document.getText();
  const eolText = document.eol === vscode.EndOfLine.LF ? '\n' : '\r\n';
  const lines = text.split(eolText);

  const diagnostics = lines.reduce((prev, lineText, lineIndex) => {
    const currentLineDiagnostics = detectSynonymsInLineText(lineText, lineIndex, globalDictionary.synonymsRegExp);
    prev.push(...currentLineDiagnostics);
    return prev;
  }, [] as vscode.Diagnostic[]);

  return diagnostics;
}

function detectSynonymsInLineText(lineText: string, lineIndex: number, synonymsRegExp: RegExp) {
  const diagnostics = [];

  const matchedTextIterator = lineText.matchAll(synonymsRegExp);

  for (let matchedTextInfo of matchedTextIterator) {
    const matchedText = matchedTextInfo[0];
    const startIndex = matchedTextInfo.index || 0;
    const endIndex = startIndex + matchedText.length;

    const startPosition = new vscode.Position(lineIndex, startIndex);
    const endPosition = new vscode.Position(lineIndex, endIndex);
    const range = new vscode.Range(startPosition, endPosition);

    const diagnostic = createDiagnostic(range, matchedText, `${matchedText} is a synonym`);
    diagnostics.push(diagnostic);
  }

  return diagnostics; 
}

function createDiagnostic(range: vscode.Range, matchedSynonym: string, message: string) {
  const diagnostic = new vscode.Diagnostic(
    range,
    message,
    vscode.DiagnosticSeverity.Information,
  );
  diagnostic.source = DIAGNOSTIC_IDENT;
  diagnostic.code = matchedSynonym;

  return diagnostic;
}
